package studio.raptor.extractor.segment;

import com.google.common.base.Joiner;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import studio.raptor.extractor.segment.config.EventSourceConfig;
import studio.raptor.extractor.segment.config.ServerConfig;
import studio.raptor.extractor.segment.entity.EventNode;
import studio.raptor.extractor.segment.holder.ExtractorServerHolder;
import studio.raptor.extractor.segment.properties.MQProperties;
import studio.raptor.extractor.segment.properties.QueueProperties;
import studio.raptor.extractor.segment.properties.ThreadProperties;
import studio.raptor.extractor.segment.properties.ZKProperties;
import studio.raptor.extractor.segment.server.ExtractorServer;
import studio.raptor.extractor.segment.service.EventNodeService;
import studio.raptor.extractor.segment.service.EventSourceConfigService;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Map;

/**
 * Created by liuyong8 on 2017/8/7.
 */
@Component
public abstract class ExtractorServerInitializer implements ApplicationRunner {

  private static final Logger log = LoggerFactory.getLogger(ExtractorServerInitializer.class);

  @Autowired
  private MQProperties mqProperties;
  @Autowired
  private QueueProperties queueProperties;
  @Autowired
  private ThreadProperties threadProperties;

  @Autowired
  private EventSourceConfigService eventSourceConfigService;
  @Autowired
  private EventNodeService eventNodeService;

  @Autowired
  ApplicationContext context;

  private static String LEADER_NODE = "/%s/leader/%s";

  @PostConstruct
  public void init() {
    System.out.println("init ExtractorServerInitializer");
  }

  @Override
  public void run(ApplicationArguments args) throws Exception {
    log.info("extractor run kindId = {}", Joiner.on(",").join(mqProperties.getEventKindId()));

    for (Integer kindId : mqProperties.getEventKindId()) {
      ServerConfig serverConfig = buildServerConfig(kindId);
      log.info("服务配置：" + serverConfig.toString());

      ExtractorServer server = buildExtractorServer(serverConfig);
      ExtractorServerHolder.addServer(server);
    }

    ExtractorServerHolder.startUp();


  }

  public void shutdown() {
    ExtractorServerHolder.shutDown();
  }

  private void addShutdownHookIfRequired() {
    Thread localShutdownHook = new Thread() {
      @Override
      public void run() {
        synchronized (this) {
          shutdown();
        }
      }
    };
    // 注册shutdown钩子
    Runtime.getRuntime().addShutdownHook(localShutdownHook);
  }


  /**
   * 组装serverConfig对象
   *
   * @param kindId kindId
   * @return serverConfig
   */
  private ServerConfig buildServerConfig(Integer kindId) throws Exception {
    ServerConfig serverConfig = new ServerConfig();
    EventSourceConfig eventSourceConfig = eventSourceConfigService
        .findEventSourceConfigByKindId(kindId);
    List<EventNode> eventNodes = eventNodeService.findNodeInfosByKindId(kindId);
    serverConfig.setKindId(kindId);
    serverConfig.setEventName(eventSourceConfig.getEventName());
    serverConfig.setSort(eventSourceConfig.getEventSort());
    serverConfig.setDatabusKindId(eventSourceConfig.getDatabusKindId());
    serverConfig.setBizName(getBizName());

    serverConfig.setEventNodes(eventNodes);

    serverConfig.setOverTime(threadProperties.getOverTime());
    serverConfig.setEventQueueSize(queueProperties.getEventQueueSize());
    serverConfig.setEventDataQueueSize(queueProperties.getEventDataQueueSize());
    serverConfig.setBuildJsonQueueSize(queueProperties.getBuildJsonQueueSize());

    serverConfig.setExtractorMQEnabled(new AtomicBoolean(true));

    return serverConfig;
  }

  /**
   *
   * @param serverConfig
   * @return
   */
  private ExtractorServer buildExtractorServer(ServerConfig serverConfig) {
    ExtractorServer extractorServer = context.getBean(ExtractorServer.class);
    extractorServer.setServerConfig(serverConfig);
    return extractorServer;
  }

  abstract protected String getBizName();
}
